/**
 * 
 */
package com.abel.manager.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.abel.domain.AuthPrincipal;
import com.abel.domain.AuthRequest;
import com.abel.domain.Person;
import com.abel.domain.contracts.EmailRequestContract;
import com.abel.domain.types.PersonType;
import com.abel.manager.AuthenticationManager;
import com.abel.manager.exception.AuthenticationException;
import com.abel.manager.exception.EmailSendException;
import com.abel.repository.AuthRepository;
import com.abel.repository.exception.InsufficientPermissionException;
import com.abel.repository.exception.InvalidUserCredentialsException;
import com.abel.repository.exception.MultipleUserNameException;
import com.abel.repository.exception.RepositoryException;
import com.abel.service.EmailService;
import com.abel.util.DomainCreator;
import com.abel.util.UserSessionLocator;
import com.abel.util.UserTypeEvaluator;

/**
 * @author admin
 *
 */
public class AuthenticationManagerImpl implements AuthenticationManager {

	protected final Log logger = LogFactory.getLog(getClass());
	
	private AuthRepository authRepository;
	
	private EmailService emailService;
	
	
	/* (non-Javadoc)
	 * @see com.abel.manager.AuthenticationManager#getAuthPrincipal(com.abel.domain.AuthRequest)
	 */
	@Override
	public AuthPrincipal getAuthPrincipal(AuthRequest authRequest)
			throws AuthenticationException, InvalidUserCredentialsException, InsufficientPermissionException {
		
		AuthPrincipal authPrincipal = null;
		
		try {
			authPrincipal = this.authRepository.getAuthPrincipal(authRequest);
			
			if (authPrincipal == null || authPrincipal.getRoles().size() == 0) {
				logger.info("@AuthenticationManagerImpl : getAuthPrincipal : No roles set for the user");
				throw new AuthenticationException("No roles set for the user");
			}
			
			//setting auth info into Threadlocal and session
			UserSessionLocator.getUserSession().setAuthPrincipal(authPrincipal);
			
			//For Regular user, creates the Person object and sets it to be used by other parts of the application
			if (UserTypeEvaluator.isRegularUser()) {
				
				Person person = DomainCreator.createPerson(PersonType.getPersonTypeByIndicator(authPrincipal.getUserType()));
				person.setUserId(authPrincipal.getUserId());
				UserSessionLocator.getUserSession().setPerson(person);
			}
		} 
		catch (RepositoryException e) {
		
			logger.info("@ : getAuthPrincipal : exception " + e);
			e.printStackTrace();
			throw new AuthenticationException("Exception while authenticating/authorizing user - " + authRequest.getUserName(),e);
		
		}
		return authPrincipal;
	}
	

	
	/* (non-Javadoc)
	 * @see com.abel.manager.AuthenticationManager#validateForgotPasswordCredentials(com.abel.domain.AuthRequest)
	 */
	@Override
	public boolean validateForgotPasswordCredentials(AuthRequest authRequest)
			throws AuthenticationException, InvalidUserCredentialsException {
		
		try {
			
			AuthPrincipal authPrincipal = this.authRepository.validateAuthCredentials(authRequest);
			
			if (authPrincipal == null) {
				return false;
			}
			//send email with the password
			EmailRequestContract requestContract = new EmailRequestContract();
			requestContract.setTo(authPrincipal.getEmail());
			requestContract.setSubject("Abel Personnel credential recovery");
			requestContract.setMessage("This message is from Abel Personnel. \n  Your current password is " + authPrincipal.getCredential());
			emailService.sendEmail(requestContract);

			return true;
		} 
		catch (RepositoryException e) {
			e.printStackTrace();
			throw new AuthenticationException(e);
		} 
		catch (MultipleUserNameException e) {
			e.printStackTrace();
			return false;
		}
		catch (EmailSendException e) {
			e.printStackTrace();
			throw new AuthenticationException(e);
		}
		catch (InvalidUserCredentialsException e) {
			return false;
		}
	}



	@Override
	public void setAuthRepository(AuthRepository authRepository) {
		this.authRepository = authRepository;
		
	}



	/**
	 * @param emailService the emailService to set
	 */
	public void setEmailService(EmailService emailService) {
		this.emailService = emailService;
	}
	
	
}
